{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "fa98944b-1495-42ec-9295-b6401868036a",
   "metadata": {},
   "source": [
    "# 简介\n",
    "\n",
    "这是一款名为‘Construction Assistant城市建设法规标准小助手’的演示应用，它展示了如何利用LangChain的工具以及ERNIEBot的functional agent来汇聚专业知识。通过利用ERNIE Bot SDK的functional agent，我们可以根据对话的上下文以及用户提出的具体问题，让大型模型在回答问题时灵活选择是否采用检索增强方式，或是直接给出答案。这种设计思路不仅丰富了大模型的领域知识，同时也保留了大模型在领域知识之外的通用对话能力。\n",
    "\n",
    "构建流程如下："
   ]
  },
  {
   "cell_type": "markdown",
   "id": "53f40c7a-0de3-4b87-bb4d-293611722bef",
   "metadata": {},
   "source": [
    "# 1. 导入第三方库\n",
    "\n",
    "主要是在导入一些必要的Python库和模块，以便实现Construction Assistant的功能。\n",
    "+ os: Python的标准库，用于与操作系统进行交互，如读写文件、管理路径等。\n",
    "+ Optional, List, Type, Dict: 这些是Python类型提示（typing模块的一部分），用于增强代码的可读性和可维护性，同时也方便开发者进行静态类型检查。\n",
    "+ BaseModel, Field: 这些都是来自Pydantic库的类，用于数据验证和设定数据模型。Field通常用于设定模型的字段。\n",
    "+ SpacyTextSplitter: 一个文本分割工具，用于将文本分割为更小的部分，如句子或短语。\n",
    "+ FAISS: 用于向量存储的模块，可能是用于存储和检索经过嵌入处理的文本或图像的向量表示。\n",
    "+ PyPDFDirectoryLoader: 用于从PDF文件中加载数据的工具。\n",
    "+ ErnieEmbeddings: 用于文本嵌入的工具，将文本转换为可以在模型中使用的向量表示。\n",
    "+ Tool, ToolParameterView: 用于创建和管理工具的基类或工具参数视图的类。\n",
    "+ FunctionalAgent: 这个类实现function calling功能的Agent的类，如问答、对话等。\n",
    "+ WholeMemory: 用于存储和管理代理的记忆的类。\n",
    "+ ERNIEBot: 实现ERNIE Bot的主要类，包含了实现对话功能的主要逻辑。\n",
    "+ AIMessage, HumanMessage, Message: 用于实现消息传递和处理的类，如机器人和人类之间的消息交互。\n",
    "+ erniebot: 这是导入erniebot模块的语句，erniebot可能是一个包含ERNIE Bot实现的主要代码库。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "3f2e9b73-88f3-4ac7-91ec-6624f6cb1b1c",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "from typing import Optional, List, Type, Dict\n",
    "from pydantic import BaseModel, Field\n",
    "from langchain.text_splitter import SpacyTextSplitter\n",
    "from langchain.vectorstores import FAISS\n",
    "from langchain.document_loaders import PyPDFDirectoryLoader\n",
    "\n",
    "from erniebot_agent.extensions.langchain.embeddings import ErnieEmbeddings\n",
    "from erniebot_agent.tools.base import Tool, ToolParameterView\n",
    "from erniebot_agent.agents.functional_agent import FunctionalAgent\n",
    "from erniebot_agent.memory.whole_memory import WholeMemory\n",
    "from erniebot_agent.chat_models.erniebot import ERNIEBot\n",
    "from erniebot_agent.messages import AIMessage, HumanMessage, Message\n",
    "import erniebot"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b9353a59-acfc-4dbd-ae27-50b7cfab6440",
   "metadata": {},
   "source": [
    "# 2. 预处理\n",
    "\n",
    "## 2.1 下载数据集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "c6f1d943-6d43-4f34-a92d-f76ab1c3ec53",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--2023-11-16 19:53:24--  https://paddlenlp.bj.bcebos.com/datasets/examples/construction_regulations.tar\n",
      "Resolving paddlenlp.bj.bcebos.com (paddlenlp.bj.bcebos.com)... 36.110.192.178\n",
      "Connecting to paddlenlp.bj.bcebos.com (paddlenlp.bj.bcebos.com)|36.110.192.178|:443... connected.\n",
      "HTTP request sent, awaiting response... 200 OK\n",
      "Length: 1239040 (1.2M) [application/x-tar]\n",
      "Saving to: ‘construction_regulations.tar.2’\n",
      "\n",
      "construction_regula 100%[===================>]   1.18M  3.72MB/s    in 0.3s    \n",
      "\n",
      "2023-11-16 19:53:25 (3.72 MB/s) - ‘construction_regulations.tar.2’ saved [1239040/1239040]\n",
      "\n",
      "x construction_regulations/\n",
      "x construction_regulations/城市管理执法办法.pdf\n",
      "x construction_regulations/建筑工程设计招标投标管理办法.pdf\n",
      "x construction_regulations/建筑业企业资质管理规定.pdf\n",
      "x construction_regulations/城市照明管理规定.pdf\n",
      "x construction_regulations/城市设计管理办法.pdf\n",
      "x construction_regulations/建筑工程施工发包与承包计价管理办法.pdf\n",
      "x construction_regulations/市政公用设施抗灾设防管理规定.pdf\n"
     ]
    }
   ],
   "source": [
    "! wget https://paddlenlp.bj.bcebos.com/datasets/examples/construction_regulations.tar\n",
    "! tar xvf construction_regulations.tar"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "e2ef2558-52f6-47e8-a182-f9d8c30bb4c1",
   "metadata": {},
   "source": [
    "## 2.2 配置 ERNIE BOT API\n",
    "\n",
    "这里使用aistudio的Access_token, 申请地址请参考[accessToken](https://aistudio.baidu.com/index/accessToken)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "02bd2731-f0d7-48ac-a02e-8cadd85b7531",
   "metadata": {},
   "outputs": [],
   "source": [
    "erniebot.api_type = \"aistudio\"\n",
    "aistudio_access_token = \"your access token\"\n",
    "erniebot.access_token = aistudio_access_token"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7ae57a90-b949-4ca4-a1b5-030910a7dcfc",
   "metadata": {},
   "source": [
    "# 3. Tool 构建\n",
    "\n",
    "##  3.1 构建Schema\n",
    "\n",
    "定义了三个类：SearchToolInputView，SearchResponseDocument，和SearchToolOutputView，它们都是ToolParameterView的子类，用于处理和描述一种特定的工具参数。这些类利用了Python的typing模块来定义字段和它们的类型，以及字段的描述。\n",
    "\n",
    "+ SearchToolInputView类定义了两个字段：query和retrieval_num。query字段是一个字符串，用于描述“规章查询语句”，这可能是用户输入的查询参数。retrieval_num字段是一个整数，描述了“检索结果数目”，默认值是5。\n",
    "+ SearchResponseDocument类定义了三个字段：document，filename和page_num。这些字段可能用于描述一个特定的搜索结果。document字段是字符串，用于存储和查询相关的规章片段。filename字段也是字符串，用于存储规章的名称。page_num字段是整数，用于描述规章的页数。\n",
    "+ SearchToolOutputView类定义了一个字段：documents，这是一个SearchResponseDocument对象的列表，用于描述搜索结果。这个字段的描述表明它包含的是“住房和城乡建设部规章中和query相关的规章片段”。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "b0adbd7c-f78a-470c-9ff1-60f3110e5bce",
   "metadata": {},
   "outputs": [],
   "source": [
    "class SearchToolInputView(ToolParameterView):\n",
    "    query: str = Field(description='规章查询语句')\n",
    "    retrieval_num: int = Field(description=\"检索结果数目\", default=5)\n",
    "\n",
    "\n",
    "class SearchResponseDocument(ToolParameterView):\n",
    "    document: str = Field(description=\"和query相关的规章片段\")\n",
    "    filename: str = Field(description=\"规章名称\")\n",
    "    page_num: int = Field(description=\"规章页数\")\n",
    "\n",
    "\n",
    "class SearchToolOutputView(ToolParameterView):\n",
    "    documents: List[SearchResponseDocument] = Field(description=\"检索结果，内容为住房和城乡建设部规章中和query相关的规章片段\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "92b422be-bb58-4641-8cba-dea3a3dddf3a",
   "metadata": {},
   "source": [
    "## 3.2 构建Faiss检索工具\n",
    "这段代码定义了一个名为FaissSearchTool的类，它是Tool的子类。这个工具被设计用于在住房和城乡建设部规章中寻找和给定查询（query）最相关的片段。\n",
    "\n",
    "1. FaissSearchTool的类属性description描述了这个工具的功能，input_type和output_type则分别指定了输入和输出的类型。\n",
    "2. 在__init__方法中，这个工具初始化了一个数据库连接。\n",
    "3. __call__方法是这个工具的核心，它是一个异步方法，接受一个查询字符串和一个检索数量，返回一个包含检索到的文档的字典。这个方法首先使用数据库的similarity_search方法获取与查询相似的文档，然后构造检索结果，最后返回一个包含检索结果的字典。\n",
    "4. examples属性返回了一个示例列表，这个列表包含一个人类消息和一个AI消息。这些消息可以用来演示这个工具的使用方法。\n",
    "\n",
    "总的来说，这个类是一个基于Faiss库的搜索工具，用于在特定的文档数据库中找到与给定查询最相关的文档。这在信息检索、问答系统等领域有广泛的应用。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "36080e36-62cf-492e-b96e-e90846f76d38",
   "metadata": {},
   "outputs": [],
   "source": [
    "class FaissSearchTool(Tool):\n",
    "    description: str = \"在住房和城乡建设部规章中寻找和query最相关的片段\"\n",
    "    input_type: Type[ToolParameterView] = SearchToolInputView\n",
    "    ouptut_type: Type[ToolParameterView] = SearchToolOutputView\n",
    "\n",
    "    def __init__(self, db):\n",
    "        self.db = db\n",
    "\n",
    "    async def __call__(self, query: str, retrieval_num: int = 5) -> Dict[str, float]:\n",
    "        docs = self.db.similarity_search(query)\n",
    "        retrieval_results = []\n",
    "        for doc in docs:\n",
    "            retrieval_results.append(\n",
    "                dict(SearchResponseDocument(\n",
    "                    document=doc.page_content,\n",
    "                    filename=doc.metadata[\"source\"],\n",
    "                    page_num=doc.metadata[\"page\"],\n",
    "                ))\n",
    "            )\n",
    "        return {\"documents\": retrieval_results}\n",
    "\n",
    "    @property\n",
    "    def examples(self) -> List[Message]:\n",
    "        return [\n",
    "                HumanMessage(\"城乡建设部规章中描述的城市管理执法的执法主体是谁？\"),\n",
    "                AIMessage(\n",
    "                    \"\",\n",
    "                    function_call={\n",
    "                        \"name\": self.tool_name,\n",
    "                        \"thoughts\": f\"这是一个住房和城乡建设部规章的问题，我们使用{self.tool_name}工具检索相关的信息，检索的query：'城市管理执法的执法主体'。\",\n",
    "                        \"arguments\": '{\"query\": \"城市管理执法的执法主体\", \"retrieval_num\": 3}',\n",
    "                    },\n",
    "                )\n",
    "            ]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2b1f9a3c-5c0e-406a-9379-66a441ffcf57",
   "metadata": {},
   "source": [
    "# 4. Construction Assistant\n",
    "## 4.1 建索引库\n",
    "\n",
    "这段代码主要功能是用于创建或加载一个FAISS索引来进行文档相似度匹配。首先，创建一个ErnieEmbeddings对象，用于生成文档的嵌入向量。aistudio_access_token是访问AI Studio的令牌，chunk_size是用于嵌入的文档块的数量。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "9cf1714d-c0c7-4e7c-9085-9db3f5bd5d77",
   "metadata": {},
   "outputs": [],
   "source": [
    "embeddings = ErnieEmbeddings(aistudio_access_token=aistudio_access_token, \n",
    "                             chunk_size=16)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "70e3286e-9398-4c63-bcea-76eadb9fee57",
   "metadata": {},
   "source": [
    "接下来利用ErnieEmbeddings来抽取向量构建索引。\n",
    "+ 如果FAISS索引文件已经存在，就使用FAISS.load_local方法加载这个索引，这个索引文件的名字就是定义的faiss_name。\n",
    "+ 如果FAISS索引不存在，则需要建索引。\n",
    "    + 第一步，使用PyPDFDirectoryLoader来从\"construction_regulations\"这个文件夹中加载PDF文档。\n",
    "    + 第二步，使用SpacyTextSplitter来将加载的文档分割成更小的部分，以便于生成嵌入向量。这个分割器主要用于中文文本，因为这里使用的pipeline是'zh_core_web_sm'，如果是初次运行，需要安装spacy并运行`python -m spacy download zh_core_web_sm`来下载中文分句模型。\n",
    "    + 第三步，通过分割后的文档创建一个新的FAISS索引，并将这个索引保存为之前定义的faiss_name。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "ba96dcab-72a6-45f3-bbab-352d0c29afa4",
   "metadata": {},
   "outputs": [],
   "source": [
    "faiss_name = \"faiss_index\"\n",
    "if os.path.exists(faiss_name):\n",
    "    db = FAISS.load_local(faiss_name, embeddings)\n",
    "else:\n",
    "    loader = PyPDFDirectoryLoader(\"construction_regulations\")\n",
    "    documents = loader.load()\n",
    "    text_splitter = SpacyTextSplitter(pipeline='zh_core_web_sm', chunk_size=320, chunk_overlap=0)\n",
    "    docs = text_splitter.split_documents(documents)\n",
    "    db = FAISS.from_documents(docs, embeddings)\n",
    "    db.save_local(faiss_name)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e3bf56d6-267e-4c0d-8451-73075c007886",
   "metadata": {},
   "source": [
    "以下代码是使用FaissSearchTool工具进行搜索的一个例子，流程大致如下：\n",
    "1. 创建FaissSearchTool对象，并传入数据库对象db。\n",
    "2. 使用await关键字对FaissSearchTool对象进行异步调用，并传入查询字符串\"城市管理执法主管部门的职责是什么？\"。\n",
    "3. 将搜索结果以格式化的形式进行打印，这里使用了pprint模块进行美化打印。最终的结果存储在变量res中。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "416a4a88-fa81-4b05-a944-cc5321ae2c04",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'documents': [{'document': '第十条 城市管理执法主管部门依法相对集中行使行政处罚权的， '\n",
      "                            '可以实施法律法规规定的与行政处罚权相关的行政强制措施。',\n",
      "                'filename': 'construction_regulations/城市管理执法办法.pdf',\n",
      "                'page_num': 2},\n",
      "               {'document': '第六条 '\n",
      "                            '城市管理执法主管部门应当加强城市管理法律法规规章的宣传普及工作，增强全民守法意识，共同维护城市管理秩序。\\n'\n",
      "                            '\\n'\n",
      "                            '  \\n'\n",
      "                            '\\n'\n",
      "                            '第七条 城市管理执法主管部门应当积极为公众监督城市管理执法活动提供条件。',\n",
      "                'filename': 'construction_regulations/城市管理执法办法.pdf',\n",
      "                'page_num': 1},\n",
      "               {'document': '其他违反法律法规和本办法规定的。   第四十条 '\n",
      "                            '非城市管理执法人员着城市管理执法制式服装的，城市管理执法主管部门应当予以纠正，依法追究法律责任。',\n",
      "                'filename': 'construction_regulations/城市管理执法办法.pdf',\n",
      "                'page_num': 10},\n",
      "               {'document': '第三章 执法主体     第十三条 '\n",
      "                            '城市管理执法主管部门按照权责清晰、事权统一、精简效能的原则设置执法队伍。   第十四条 直辖市、 '\n",
      "                            '设区的市城市管理执法推行市级执法或者区级执法。   '\n",
      "                            '直辖市、设区的市的城市管理执法事项，市辖区人民政府城市管理执法主管部门能够承担的，可以实行区级执法。   '\n",
      "                            '直辖市、 设区的市人民政府城市管理执法主管部门可以承担跨区域和重大复杂违法案件的查处。',\n",
      "                'filename': 'construction_regulations/城市管理执法办法.pdf',\n",
      "                'page_num': 3}]}\n"
     ]
    }
   ],
   "source": [
    "tool = FaissSearchTool(db=db)\n",
    "res = await tool(query=\"城市管理执法主管部门的职责是什么？\")\n",
    "from pprint import pprint\n",
    "pprint(res)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "82569b9e-6549-4cdc-9e39-27318a9f4aec",
   "metadata": {},
   "source": [
    "## 4.2 构建Construction Assistant\n",
    "Construction Assistant可以自主决定什么时候选择调用工具，什么时候进行聊天，以下是一个自主调用工具的示例。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "d813cda5-2c59-4af7-b723-373283e8defd",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建一个ERNIEBot实例，使用\"ernie-bot-8k\"模型。\n",
    "llm = ERNIEBot(model=\"ernie-bot-8k\")\n",
    "# 创建一个WholeMemory实例。这可能是一个用于存储对话历史和上下文信息的类，有助于模型理解和持续对话。  \n",
    "memory = WholeMemory()\n",
    "# 创建一个FunctionalAgent实例。这个代理将使用上面创建的ERNIEBot模型和WholeMemory，同时传入了一个名为tool的工具。\n",
    "agent = FunctionalAgent(llm=llm, tools=[tool], memory=memory)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "db269276-a35a-4a4c-bfcd-41640a6de622",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Run][Start] Agent <erniebot_agent.agents.functional_agent.FunctionalAgent object at 0x123884090> starts running with input: 城乡建设部规章中，城市管理执法第三章，第十三条是什么？\n",
      "[LLM][Start] LLM <erniebot_agent.chat_models.erniebot.ERNIEBot object at 0x10f3fe8d0> starts running with input: [<erniebot_agent.messages.HumanMessage object at 0x10f41a290>]\n",
      "[LLM][End] LLM <erniebot_agent.chat_models.erniebot.ERNIEBot object at 0x10f3fe8d0> finished running with output: role: assistant, function_call: {'name': 'FaissSearchTool', 'thoughts': '用户想要查询城乡建设部规章中关于城市管理执法第三章，第十三条的内容。我可以使用FaissSearchTool工具来查询相关内容。', 'arguments': '{\"query\":\"城市管理执法第三章，第十三条\",\"retrieval_num\":1}'}\n",
      "[Tool][Start] Tool <__main__.FaissSearchTool object at 0x12370fd50> starts running with input: \n",
      "{\n",
      "  \"query\": \"城市管理执法第三章，第十三条\",\n",
      "  \"retrieval_num\": 1\n",
      "}\n",
      "[Tool][End] Tool <__main__.FaissSearchTool object at 0x12370fd50> finished running with output: \n",
      "{\n",
      "  \"documents\": [\n",
      "    {\n",
      "      \"document\": \"第十条 城市管理执法主管部门依法相对集中行使行政处罚权的， 可以实施法律法规规定的与行政处罚权相关的行政强制措施。\",\n",
      "      \"filename\": \"construction_regulations/城市管理执法办法.pdf\",\n",
      "      \"page_num\": 2\n",
      "    },\n",
      "    {\n",
      "      \"document\": \"第六条 城市管理执法主管部门应当加强城市管理法律法规规章的宣传普及工作，增强全民守法意识，共同维护城市管理秩序。\\n\\n  \\n\\n第七条 城市管理执法主管部门应当积极为公众监督城市管理执法活动提供条件。\",\n",
      "      \"filename\": \"construction_regulations/城市管理执法办法.pdf\",\n",
      "      \"page_num\": 1\n",
      "    },\n",
      "    {\n",
      "      \"document\": \"第三章 执法主体     第十三条 城市管理执法主管部门按照权责清晰、事权统一、精简效能的原则设置执法队伍。   第十四条 直辖市、 设区的市城市管理执法推行市级执法或者区级执法。   直辖市、设区的市的城市管理执法事项，市辖区人民政府城市管理执法主管部门能够承担的，可以实行区级执法。   直辖市、 设区的市人民政府城市管理执法主管部门可以承担跨区域和重大复杂违法案件的查处。\",\n",
      "      \"filename\": \"construction_regulations/城市管理执法办法.pdf\",\n",
      "      \"page_num\": 3\n",
      "    },\n",
      "    {\n",
      "      \"document\": \"住房和城乡建设部规章 \\n   X住房和城乡建设部发布  \\n- 9 -   第三十条 城市管理执法主管部门不得对罚款、 没收违法所得设定任务和目标。   \\n\\n罚款、没收违法所得的款项，应当按照规定全额上缴。   第三十一条 城市管理执法主管部门应当确定法制审核机构，配备一定比例符合条件的法制审核人员，对重大执法决定在执法主体、管辖权限、执法程序、事实认定、法律适用等方面进行法制审核。   \\n\\n第三十二条 城市管理执法主管部门开展执法活动， 应当使用统一格式的行政执法文书。\\n\\n  \\n\\n第三十三条 行政执法文书的送达， 依照民事诉讼法等法律规定执行。\",\n",
      "      \"filename\": \"construction_regulations/城市管理执法办法.pdf\",\n",
      "      \"page_num\": 8\n",
      "    }\n",
      "  ]\n",
      "}\n",
      "[LLM][Start] LLM <erniebot_agent.chat_models.erniebot.ERNIEBot object at 0x10f3fe8d0> starts running with input: [<erniebot_agent.messages.HumanMessage object at 0x10f41a290>, <erniebot_agent.messages.AIMessage object at 0x1233d3710>, <erniebot_agent.messages.FunctionMessage object at 0x118a535d0>]\n",
      "[LLM][End] LLM <erniebot_agent.chat_models.erniebot.ERNIEBot object at 0x10f3fe8d0> finished running with output: role: assistant, content: 根据您提供的查询语句，我找到了城市管理执法第三章，第十三条的相关内容。具体如下：\n",
      "\n",
      "住房和城乡建设部规章中规定，城市管理执法第三章，第十三条的内容为：“城市管理执法主管部门应当加强城市管理法律法规规章的宣传普及工作，增强全民守法意识，共同维护城市管理秩序。”\n",
      "\n",
      "如果您需要更详细的内容或者对其他方面有疑问，请随时告诉我。\n",
      "[Run][End] Agent <erniebot_agent.agents.functional_agent.FunctionalAgent object at 0x123884090> finished running with output: AgentResponse(content='根据您提供的查询语句，我找到了城市管理执法第三章，第十三条的相关内容。具体如下：\\n\\n住房和城乡建设部规章中规定，城市管理执法第三章，第十三条的内容为：“城市管理执法主管部门应当加强城市管理法律法规规章的宣传普及工作，增强全民守法意识，共同维护城市管理秩序。”\\n\\n如果您需要更详细的内容或者对其他方面有疑问，请随时告诉我。', chat_history=[<erniebot_agent.messages.HumanMessage object at 0x10f41a290>, <erniebot_agent.messages.AIMessage object at 0x1233d3710>, <erniebot_agent.messages.FunctionMessage object at 0x118a535d0>, <erniebot_agent.messages.AIMessage object at 0x123885ad0>], actions=[AgentAction(tool_name='FaissSearchTool', tool_args='{\"query\":\"城市管理执法第三章，第十三条\",\"retrieval_num\":1}')], status='FINISHED')\n",
      "{'role': 'user', 'content': '城乡建设部规章中，城市管理执法第三章，第十三条是什么？'}\n",
      "{'role': 'assistant', 'content': '', 'function_call': {'name': 'FaissSearchTool', 'thoughts': '用户想要查询城乡建设部规章中关于城市管理执法第三章，第十三条的内容。我可以使用FaissSearchTool工具来查询相关内容。', 'arguments': '{\"query\":\"城市管理执法第三章，第十三条\",\"retrieval_num\":1}'}}\n",
      "{'role': 'function', 'name': 'FaissSearchTool', 'content': '{\"documents\": [{\"document\": \"第十条 城市管理执法主管部门依法相对集中行使行政处罚权的， 可以实施法律法规规定的与行政处罚权相关的行政强制措施。\", \"filename\": \"construction_regulations/城市管理执法办法.pdf\", \"page_num\": 2}, {\"document\": \"第六条 城市管理执法主管部门应当加强城市管理法律法规规章的宣传普及工作，增强全民守法意识，共同维护城市管理秩序。\\\\n\\\\n  \\\\n\\\\n第七条 城市管理执法主管部门应当积极为公众监督城市管理执法活动提供条件。\", \"filename\": \"construction_regulations/城市管理执法办法.pdf\", \"page_num\": 1}, {\"document\": \"第三章 执法主体     第十三条 城市管理执法主管部门按照权责清晰、事权统一、精简效能的原则设置执法队伍。   第十四条 直辖市、 设区的市城市管理执法推行市级执法或者区级执法。   直辖市、设区的市的城市管理执法事项，市辖区人民政府城市管理执法主管部门能够承担的，可以实行区级执法。   直辖市、 设区的市人民政府城市管理执法主管部门可以承担跨区域和重大复杂违法案件的查处。\", \"filename\": \"construction_regulations/城市管理执法办法.pdf\", \"page_num\": 3}, {\"document\": \"住房和城乡建设部规章 \\\\n   X住房和城乡建设部发布  \\\\n- 9 -   第三十条 城市管理执法主管部门不得对罚款、 没收违法所得设定任务和目标。   \\\\n\\\\n罚款、没收违法所得的款项，应当按照规定全额上缴。   第三十一条 城市管理执法主管部门应当确定法制审核机构，配备一定比例符合条件的法制审核人员，对重大执法决定在执法主体、管辖权限、执法程序、事实认定、法律适用等方面进行法制审核。   \\\\n\\\\n第三十二条 城市管理执法主管部门开展执法活动， 应当使用统一格式的行政执法文书。\\\\n\\\\n  \\\\n\\\\n第三十三条 行政执法文书的送达， 依照民事诉讼法等法律规定执行。\", \"filename\": \"construction_regulations/城市管理执法办法.pdf\", \"page_num\": 8}]}'}\n",
      "{'role': 'assistant', 'content': '根据您提供的查询语句，我找到了城市管理执法第三章，第十三条的相关内容。具体如下：\\n\\n住房和城乡建设部规章中规定，城市管理执法第三章，第十三条的内容为：“城市管理执法主管部门应当加强城市管理法律法规规章的宣传普及工作，增强全民守法意识，共同维护城市管理秩序。”\\n\\n如果您需要更详细的内容或者对其他方面有疑问，请随时告诉我。', 'function_call': None}\n"
     ]
    }
   ],
   "source": [
    "# 定义一个查询字符串，这个查询是关于\"城乡建设部规章中，城市管理执法第三章，第十三条\"的内容。  \n",
    "query = \"城乡建设部规章中，城市管理执法第三章，第十三条是什么？\"\n",
    "response = await agent.async_run(query)\n",
    "# 使用agent的async_run方法来异步执行查询。由于这是异步操作，因此需要使用'await'关键字。 \n",
    "messages = response.chat_history\n",
    "for item in messages:\n",
    "    print(item.to_dict())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c8cce276-e301-48ab-bdfa-bfd61060a446",
   "metadata": {},
   "source": [
    "以下是一个自主聊天的示例："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "30bbb845-f7ed-431e-9917-51068052966b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Run][Start] Agent <erniebot_agent.agents.functional_agent.FunctionalAgent object at 0x123884090> starts running with input: 您好\n",
      "[LLM][Start] LLM <erniebot_agent.chat_models.erniebot.ERNIEBot object at 0x10f3fe8d0> starts running with input: [<erniebot_agent.messages.HumanMessage object at 0x10f41a290>, <erniebot_agent.messages.AIMessage object at 0x123885ad0>, <erniebot_agent.messages.HumanMessage object at 0x1233d0a50>]\n",
      "[LLM][End] LLM <erniebot_agent.chat_models.erniebot.ERNIEBot object at 0x10f3fe8d0> finished running with output: role: assistant, content: 你好！有什么我可以帮助你的吗？\n",
      "[Run][End] Agent <erniebot_agent.agents.functional_agent.FunctionalAgent object at 0x123884090> finished running with output: AgentResponse(content='你好！有什么我可以帮助你的吗？', chat_history=[<erniebot_agent.messages.HumanMessage object at 0x1233d0a50>, <erniebot_agent.messages.AIMessage object at 0x1233c2550>], actions=[], status='FINISHED')\n",
      "{'role': 'user', 'content': '您好'}\n",
      "{'role': 'assistant', 'content': '你好！有什么我可以帮助你的吗？', 'function_call': None}\n"
     ]
    }
   ],
   "source": [
    "query = \"您好\"\n",
    "response = await agent.async_run(query)\n",
    "messages = response.chat_history\n",
    "for item in messages:\n",
    "    print(item.to_dict())"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.10.13 ('py310')",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.13"
  },
  "vscode": {
   "interpreter": {
    "hash": "9345dcc06c282d741efc85f9a9d5e3db79cc12ed5ca52c1d1ae239e559abfbe9"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
